using System;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml;
using System.Reflection;
using Services;
using Utilities.Menu.UIElements;
using SuperTicTacToe.Resources;
using Services.Menu;
using Utilities;
using SuperTicTacToe.Menu;

namespace SuperTicTacToe
{
    public enum State { Playing, Ended, Pair }
    class Tile2D : MyButton
    {
        public int player_index;
        //Color color;
        public Tile2D(Rectangle rectangle, Texture2D texture)
            : base(rectangle, texture, Color.White)
        {
            this.player_index = -1;
        }

        public override void Draw(SpriteBatch batch)
        {
            if (player_index == -1) return;
            batch.Draw(texture, rectangle, textureColor);
        }
        public void SetIndex(int index)
        {
            if (player_index != -1)
                return;
            player_index = index;
            switch (index)
            {
                case 0:
                    textureColor = ConfigMenu.color1;
                    break;
                case 1:
                    textureColor = ConfigMenu.color2;
                    break;
                case 2:
                    textureColor = ConfigMenu.color3;
                    break;
                //case 3:
                //    textureColor = ConfigMenu.color4;
                //    break;
            }
        }
    }
    
    class Level2D : DrawableGameComponent
    {
        InputManager input_manager;
        Texture2D screen_bg, whiteTexture, whiteBox;
        SpriteFont font, font_t, font_p;
        MyButton menu, title;
        SpriteBatch spriteBatch;
        StateManager stateManager;
        protected float press_wait;
        protected readonly float PRESS_INTERVAL = 0.5f;
        ArrayList<Player> players;
        Color textColor;
        Texture2D cpu_t, human_t;
        Rectangle deck_r;
        Texture2D deck_t;
        int size;
        Tile2D[,] deck;
        int current_player;
        //int winner;
        State gameState;
        public Level2D(Game game, StateManager stateManager, ArrayList<Player> players, int size)
            : base(game)
        {
            this.stateManager = stateManager;
            this.players = players;
            this.size = size;
        }

        public override void Initialize()
        {
            spriteBatch = Game.Services.GetService(typeof(SpriteBatch)) as SpriteBatch;
            //stateManager = Game.Services.GetService(typeof(AStateManager)) as StateManager;
            Game.Services.RemoveService(typeof(IInputManager));
            input_manager = new InputManager(Game);
            Game.Components.Add(input_manager);
            input_manager.OnTap += on_tap;
            base.Initialize();
        }

        protected override void LoadContent()
        {
            //buttonbg = Game.Content.Load<Texture2D>("Levels/whiteTexture");
            
            font = Game.Content.Load<SpriteFont>("Fonts/Arial26Ptx");
            font_p = Game.Content.Load<SpriteFont>("Fonts/Arial26Ptx");
            font_t = Game.Content.Load<SpriteFont>("Fonts/Arial54Ptx");
            screen_bg = Game.Content.Load<Texture2D>("Textures/LevelBackground");
            
            whiteBox = Game.Content.Load<Texture2D>("Textures/bar_box");
            whiteTexture = Game.Content.Load<Texture2D>("Textures/WhitePixel");
            
            cpu_t = Game.Content.Load<Texture2D>("Textures/cpu");
            human_t = Game.Content.Load<Texture2D>("Textures/human");
            var tile = Game.Content.Load<Texture2D>("Textures/cross");

            textColor = new Color(8, 141, 217);
            
            menu = new MyButton(new Rectangle(380, 0, 100, 80), Strings.Menu, textColor, font);
            var deck_x = 40;
            var deck_y = 200;
            deck_r = new Rectangle(deck_x, deck_y, 400, 400);

            var s = size == 0 ? "small" : size == 1 ? "medium" : "big";

            deck_t = Game.Content.Load<Texture2D>("Textures/" + s);

            title = new MyButton(new Rectangle(20, 0, 440, 80), Strings.Menu_NewGame_Title, textColor, font_t);
            size += 3;
            deck = new Tile2D[size, size];
            int tile_size = 0, offset = 0, border_offset = 0;

            switch (size)
            {
                case 3:
                    tile_size = 65;
                    border_offset = 65;
                    offset = 35;
                    break;
                case 4:
                    tile_size = 60;
                    border_offset = 45;
                    offset = 20;
                    break;
                case 5:
                    tile_size = 50;
                    border_offset = 40;
                    offset = 16;
                    break;

            }

            for (int x = 0; x < size; x++)
            {
                for (int y = 0; y < size; y++)
                {
                    deck[x, y] = new Tile2D(new Rectangle(deck_x + border_offset + y * (tile_size + offset), deck_y + border_offset + x * (tile_size + offset),
                        tile_size, tile_size), tile);
                }
            }
            gameState = State.Playing;
            move_delay = 0;
            base.LoadContent();
        }
        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(IInputManager));
            Game.Components.Remove(input_manager);
            base.Dispose(disposing);
        }
        public void DisposeMenu()
        {
            Game.Services.RemoveService(typeof(IInputManager));
            Game.Components.Remove(input_manager);
            this.Dispose();
        }
        float move_delay;
        public override void Update(GameTime gameTime)
        {
            if (press_wait < PRESS_INTERVAL)
                press_wait += (float)gameTime.ElapsedGameTime.TotalSeconds;
            
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                stateManager.SelectMainMenu();
            }

            //if (!players[current_player].isHuman)
            //{
            //    move_delay+=(float)gameTime.ElapsedGameTime.TotalSeconds;
            //    if (move_delay > 1)
            //    {
            //        ComputeMove();
            //        move_delay = 0;
            //    }
            //}

            base.Update(gameTime);
        }

        Rectangle bg_rect = new Rectangle(0, 0, 480, 800);
        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            spriteBatch.Draw(screen_bg, bg_rect, Color.White);

            title.Draw(spriteBatch);

            menu.Draw(spriteBatch);

            spriteBatch.Draw(deck_t, deck_r, Color.White);
            for (int x = 0; x < deck.GetLength(0); x++)
                for (int y = 0; y < deck.GetLength(1); y++)
                    deck[x, y].Draw(spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        }
        Point tp = new Point();
        void on_tap(Vector2 tap_position)
        {
            if (press_wait < PRESS_INTERVAL) return;
            tp.X = (int)tap_position.X;
            tp.Y = (int)tap_position.Y;

            if (menu.tapped_on(tp))
                stateManager.SelectMainMenu();
            if(gameState== State.Playing && players[current_player].isHuman)
                for(int x=0;x<deck.GetLength(0);x++)
                    for(int y=0;y<deck.GetLength(1);y++)
                        if (deck[x, y].tapped_on(tp))
                        {
                            deck[x, y].SetIndex(current_player);
                            CheckDeck(x,y);
                            if (gameState == State.Playing)
                                NextTurn();
                            return;
                        }
        }
        
        void NextTurn()
        {
            current_player++;
            if (current_player >= players.Count)
                current_player = 0;
        }
        void CheckDeck(int last_x, int last_y)
        {
            int player = deck[last_x,last_y].player_index;
            bool win = true;
            int tile=0;
            for (int i = 0; i < size && win; i++)
            {
                if (deck[i, last_y].player_index == player)
                    tile++;
                else
                    win = false;
            }
            if (win && tile == size)
            {
                gameState = State.Ended;
                return;
            }
            win = true;
            tile = 0;
            for (int i = 0; i < size && win; i++)
            {
                if (deck[last_x, i].player_index == player)
                    tile++;
                else
                    win = false;
            }
            if (win && tile == size)
            {
                gameState = State.Ended;
                return;
            }
            win = true;
            tile = 0;
            for (int i = 0; i < size && win; i++)
            {
                if (deck[i, i].player_index == player)
                    tile++;
                else
                    win = false;
            }
            if (win && tile == size)
            {
                gameState = State.Ended;
                return;
            }
            win = true;
            tile = 0;
            for (int i = 0; i < size && win; i++)
            {
                if (deck[i, size - i -1].player_index == player)
                    tile++;
                else
                    win = false;
            }
            if (win && tile == size)
            {
                gameState = State.Ended;
                return;
            }
            var occupied = 0;
            for (int i = 0; i < size; i++)
                for (int j = 0; j < size; j++)
                    if (deck[i, j].player_index != -1)
                        occupied++;
            if (occupied == size * size)
                gameState = State.Pair;
        }

        //void ComputeMove()
        //{
        //    int[,] intdeck = new int[size, size];
        //    for (int i = 0; i < size; i++)
        //        for (int j = 0; j < size; j++)
        //            intdeck[i, j] = deck[i, j].player_index;
        //    for (int time = 0; time < 4; time++)
        //    {
        //        int[,] tiles = new int[,]{
        //        { -1,current_player,current_player},
        //        {-1,-1,-1},
        //        {-1,-1,-1}
        //    };





        //    }
        //}
        //bool checkPattern(int[,] tiles)
        //{

        //    return false;
        //}
    }
}
